<?php
declare (strict_types=1);

namespace quick\admin\library\service;


use app\common\library\Email;
use PHPMailer\PHPMailer\PHPMailer;
use quick\admin\Service;
use think\App;

/**
 *
 * Class EmailService
 * @package quick\librarys
 */
class EmailService extends Service
{

    /**
     * @var array
     */
    public array $options = [
        'charset' => 'utf-8',
        'debug' => false,
        'mail_type' => 1,
    ];

    public array $config = [
        'mail_sender_mail' => 'SMTP 发件人邮箱',
        'mail_verification' => 'SMTP 验证方式',
        'mail_user' => 'SMTP 用户名',
        'mail_server' => 'SMTP 服务器',
        'mail_port' => 'SMTP端口',
        'mail_password' => 'SMTP 密码',
    ];

    public PHPMailer $mail;


    /**
     * 错误内容
     */
    protected $_error = '';

    /**
     * 系统配置
     * @return array
     */
    private function getConfig(): array
    {
        $config = [];
        foreach ($this->config as $key => $item) {
            $value = sysConfig('system_mail.' . $key);
            !empty($value) && $config[$key] = $value;
        }
        return $config;
    }


    /**
     * @param App $app
     * @param array $options
     */
    public function __construct(App $app, $options = [])
    {
        $this->app = $app;
        $this->initialize($options);
    }


    /**
     * @param array $options
     * @return Service
     * @throws \PHPMailer\PHPMailer\Exception
     */
    protected function initialize(array $options = []): Service
    {

        $this->options = array_merge($this->options, $this->getConfig());
        $this->options = array_merge($this->options, $options);
        $secureArr = ['tls' => 'tls', 'ssl' => 'ssl'];
        $this->mail = new PHPMailer(true);
        $this->mail->CharSet = $this->options['charset'];
        if ($this->options['mail_type'] == 1) {
            $this->mail->SMTPDebug = $this->options['debug'];
            $this->mail->isSMTP();
            $this->mail->SMTPAuth = true;
        } else {
            $this->mail->isMail();
        }

        $this->mail->Host = $this->options['mail_server'] ?? '';
        $this->mail->Username = $this->options['mail_user'] ?? '';
        $this->mail->Password = $this->options['mail_password'] ?? '';
        $this->mail->SMTPSecure = $secureArr[$this->options['mail_verification']] ?? '';
        $this->mail->Port = $this->options['mail_port'] ?? '';
        $this->from($this->options['mail_sender_mail'], $this->options['mail_user']);
        return $this;
    }

    /**
     * 设置发件人
     * @param string $email 发件人邮箱
     * @param string $name 发件人名称
     * @return $this
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function from(string $email, string $name = ''): self
    {
        $this->mail->setFrom($email, $name);
        return $this;
    }


    /**
     * 设置收件人
     * @param array|string $email 收件人
     * @param string $name 收件人名称
     * @return $this
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function to($email, string $name = ''): self
    {
        $emailArr = $this->buildAddress($email);
        foreach ($emailArr as $address => $name) {
            $this->mail->addAddress($address, $name);
        }

        return $this;
    }


    /**
     * 添加抄送
     * @param array|string $email 收件人
     * @param string $name 收件人名称
     * @return $this
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function addCC($email, string $name = ''): self
    {
        $emailArr = $this->buildAddress($email);
        foreach ($emailArr as $address => $name) {
            $this->mail->addCC($address, $name);
        }
        return $this;
    }

    /**
     * 设置密送
     * @param array|string $email 收件人
     * @param string $name 收件人名称
     * @return $this
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function addBcc($email, string $name = ''): self
    {
        $emailArr = $this->buildAddress($email);
        foreach ($emailArr as $address => $name) {
            $this->mail->addBCC($address, $name);
        }
        return $this;
    }

    /**
     * 设置邮件正文
     * @param string $title 主题
     * @param string $body 邮件下方
     * @param bool $isHtml 是否HTML格式
     * @return $this
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function message(string $title, string $body, bool $isHtml = true): self
    {
        $this->mail->Subject = $title;
        if ($isHtml) {
            $this->mail->msgHTML($body);
        } else {
            $this->mail->Body = $body;
        }
        return $this;
    }

    /**
     * 添加附件
     * @param string $path 附件路径
     * @param string $name 附件名称
     * @return $this
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function attachment(string $path, string $name = ''): self
    {
        $this->mail->addAttachment($path, $name);
        return $this;
    }

    /**
     * @param $emails
     * @return array
     */
    protected function buildAddress($emails): array
    {
        $emails = is_array($emails) ? $emails : explode(',', str_replace(";", ",", $emails));
        $result = [];
        foreach ($emails as $key => $value) {
            $email = is_numeric($key) ? $value : $key;
            $result[$email] = is_numeric($key) ? "" : $value;
        }
        return $result;
    }

    /**
     * 发送邮件
     * @return boolean
     */
    public function send()
    {
        $result = false;
        if (in_array($this->options['mail_type'], [1, 2])) {
            try {
                $result = $this->mail->send();
            } catch (\PHPMailer\PHPMailer\Exception $e) {
                $this->setError($e->getMessage());
            }

            $this->setError($result ? '' : $this->mail->ErrorInfo);
        } else {
            //邮件功能已关闭
            $this->setError(__('Mail already closed'));
        }
        return $result;
    }

    /**
     * 获取最后产生的错误
     * @return string
     */
    public function getError()
    {
        return $this->_error;
    }

    /**
     * 设置错误
     * @param string $error 信息信息
     */
    protected function setError($error)
    {
        $this->_error = $error;
    }


}
